#include "RssFeed.h"

#include <libxml++/libxml++.h>
#include <libxml++/nodes/cdatanode.h>
#include <glibmm/unicode.h>

using namespace xmlpp;
using namespace Glib;

void trim(string& str)
{
  string::size_type pos1 = str.find_first_not_of(" \r\n\t");
  string::size_type pos2 = str.find_last_not_of(" \r\n\t");
  str = str.substr(pos1 == string::npos ? 0 : pos1, 
    pos2 == string::npos ? str.length() - 1 : pos2 - pos1 + 1);
}

static string readSubElementText(Element * el, string name)
{
    list < Node * >nodes = el->get_children(name);
    string content;

    if (nodes.size() > 0) {
        Element *child = dynamic_cast < Element * >(nodes.front());
        
        if (child && child->has_child_text())
            content = child->get_child_text()->get_content();
        
        trim(content);
        if(content == "")
        {
            list<Node*> cdatas = child->get_children();
            for(list<Node*>::iterator i = cdatas.begin(); i != cdatas.end(); i++)
            {
                CdataNode* cdata = dynamic_cast<CdataNode*>(*i);
                if(cdata)
                {
                    content = cdata->get_content();
                    break;
                }
            }
        }
    }

    return content;
}

static Post readPost(Element * el)
{
    Post p;
    p.title = readSubElementText(el, "title");
    p.link = readSubElementText(el, "link");
    p.content = readSubElementText(el, "description");
    p.description = p.content;
    p.author = "";
    return p;
}

RssFeed RssFeed::FromXml(string xml)
{
    RssFeed feed;
    DomParser parser;

    parser.parse_memory(xml.data());

    Element *root = parser.get_document()->get_root_node();

    Element *channel =
	dynamic_cast < Element * >(root->get_children("channel").front());

    vector < Post > posts;
    if (channel == NULL) {
	cout << "no channel found " << endl;
	return feed;
    }

    feed.title = readSubElementText(channel, "title");
    feed.description = readSubElementText(channel, "description");
    feed.author = readSubElementText(channel, "author");
    
    list < Node * >children = channel->get_children();
    for (list < Node * >::iterator i = children.begin();
	 i != children.end(); i++) {
	Node *node = *i;
	// cout << "Read node " << node->get_name() << endl;
	if (node->get_name() == "item" && dynamic_cast < Element * >(node)) {
	    // cout << "found item " << endl; 
	    Element *el = dynamic_cast < Element * >(node);
	    Post post = readPost(el);
	    posts.push_back(post);
	}
    }
    feed.setPosts(posts);

    return feed;
}
